package org.example;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.RandomStringUtils;
import org.example.collectors.po.Order;
import org.example.collectors.po.OrderTypeEnum;
import org.junit.Test;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class CollectorsDemo {

    @Test
    public void to() {
        List<Order> orderList = new ArrayList<>();
        orderList.add(new Order());
        log.info("toList: {}", orderList.stream().map(Order::getOrderId).collect(Collectors.toList()));
        log.info("toSet: {}", orderList.stream().map(Order::getOrderTypeEnum).collect(Collectors.toSet()));
        Set<String> resultSet =
            orderList.stream().map(Order::getOrderName).collect(Collectors.toCollection(TreeSet::new));
        log.info("toCollection: {}", resultSet);
    }

    @Test
    public void toMapDemo() {
        List<Order> orderList = new ArrayList<>();
        orderList.add(generateOrder(1L));
        orderList.add(generateOrder(2L));
        orderList.add(generateOrder(2L));
        Map<Long, Order> id2OrderMap = orderList.stream()
            .collect(Collectors.toMap(Order::getOrderId, Function.identity(), (a, b) -> b, HashMap::new));
        log.info("toList: {}", id2OrderMap);
        Map<Long, Order> id2OrderMap2 = orderList.stream()
            .collect(Collectors.toMap(Order::getOrderId, Function.identity(), CollectorsDemo::errorLogBiOp));
        log.info("toList: {}", id2OrderMap2);
        Map<Long, Order> id2OrderMap3 =
            orderList.stream().collect(Collectors.toMap(Order::getOrderId, Function.identity(), (a, b) -> b));
        log.info("toList: {}", id2OrderMap3);
    }

    @Test
    public void groupingByDemo() {
        List<Order> orderList = new ArrayList<>();
        orderList.add(generateOrder(1L));
        orderList.add(generateOrder(2L));
        orderList.add(generateOrder(2L));
        // 一个参数
        Map<OrderTypeEnum, List<Order>> orderTypeEnum2ListMap =
            orderList.stream().collect(Collectors.groupingBy(Order::getOrderTypeEnum));
        // 两个参数
        Map<OrderTypeEnum, Set<String>> orderTypeEnum2NameSetMap = orderList.stream().collect(Collectors
            .groupingBy(Order::getOrderTypeEnum, Collectors.mapping(Order::getOrderName, Collectors.toSet())));
        // 三个参数
        TreeMap<OrderTypeEnum, Set<String>> orderTypeEnum2NameSetTreeMap =
            orderList.stream().collect(Collectors.groupingBy(Order::getOrderTypeEnum, TreeMap::new,
                Collectors.mapping(Order::getOrderName, Collectors.toSet())));
    }

    @Test
    public void partitioningByDemo() {
        List<Order> orderList = new ArrayList<>();
        orderList.add(generateOrder(1L));
        orderList.add(generateOrder(2L));
        orderList.add(generateOrder(2L));
        Integer BIG_ORDER_COUNT = 10000;
        // 一个参数
        Map<Boolean, List<Order>> bigOrderMap = orderList.stream()
            .collect(Collectors.partitioningBy(order -> order.getOrderItems().size() > BIG_ORDER_COUNT));
        // 二个参数,第二个参数是一个collector,对List进行二次处理
        Map<Boolean, Long> bigOrderCountMap = orderList.stream().collect(
            Collectors.partitioningBy(order -> order.getOrderItems().size() > BIG_ORDER_COUNT, Collectors.counting()));
    }

    private Order generateOrder(long l) {
        Order order = new Order();
        order.setOrderId(l);
        order.setOrderName(RandomStringUtils.random(10));
        order.setOrderTypeEnum(OrderTypeEnum.MAIN);
        order.setOrderItems(new ArrayList<>());
        return order;
    }

    private static Order errorLogBiOp(Order a, Order b) {
        log.error("元素重复 {} - {}", a, b);
        return b;
    }
}
